package qualomelhor.gwt.modules.client;

import java.util.ArrayList;

import javax.naming.directory.SearchControls;

import qualomelhor.gwt.modules.client.event.BuscaImagemExecutadaEvent;
import qualomelhor.gwt.modules.client.event.ImagemDisponivelEvent;
import qualomelhor.gwt.modules.client.event.ImagemNaoDisponivelEvent;
import qualomelhor.gwt.modules.client.event.ImagensJaSelecionadasEvent;
import qualomelhor.gwt.modules.client.interfaces.BuscaImagemEventHandler;
import qualomelhor.gwt.modules.client.interfaces.BuscaImagemExecutadaEventHandler;
import com.google.gwt.core.client.GWT;
import com.google.gwt.core.client.JsArray;
import com.google.gwt.dom.client.Style.FontWeight;
import com.google.gwt.dom.client.Style.Position;
import com.google.gwt.dom.client.Style.Unit;
import com.google.gwt.dom.client.Style.Visibility;
import com.google.gwt.event.dom.client.ClickEvent;
import com.google.gwt.event.dom.client.ClickHandler;
import com.google.gwt.event.dom.client.ErrorEvent;
import com.google.gwt.event.dom.client.ErrorHandler;
import com.google.gwt.event.dom.client.LoadEvent;
import com.google.gwt.event.dom.client.LoadHandler;
import com.google.gwt.event.shared.HandlerManager;
import com.google.gwt.search.client.ImageSearch;
import com.google.gwt.search.client.Result;
import com.google.gwt.search.client.ResultClass;
import com.google.gwt.search.client.ResultSetSize;
import com.google.gwt.search.client.Search;
import com.google.gwt.search.client.SearchControl;
import com.google.gwt.search.client.SearchControlOptions;
import com.google.gwt.search.client.SearchResultsHandler;
import com.google.gwt.search.client.WebResult;
import com.google.gwt.user.client.Window;
import com.google.gwt.user.client.ui.AbsolutePanel;
import com.google.gwt.user.client.ui.Button;
import com.google.gwt.user.client.ui.Composite;
import com.google.gwt.user.client.ui.FlexTable;
import com.google.gwt.user.client.ui.Image;
import com.google.gwt.user.client.ui.Label;
import com.google.gwt.user.client.ui.ScrollPanel;
import com.google.gwt.user.client.ui.VerticalPanel;

public class BuscaImagemWidget extends Composite {

	private final AbsolutePanel container;
	private VerticalPanel vertPanelEspera;
	private FlexTable resultsTable;
	private ScrollPanel scroll;
	private Button btnDone;
	private ArrayList<String> listImages;
	private int status;
	private int numImagensASeremBuscadas;
	private int numImagensCarregadas;
	private SearchControlOptions options;
	//Create the listener list
	private HandlerManager handlerManager = new HandlerManager(null);
	private LanguageConstants constants = GWT.create(LanguageConstants.class);

	public BuscaImagemWidget() {
		container = new AbsolutePanel();
		container.setStylePrimaryName("boxRounded3");
		initWidget(container);
		container.setWidth("228px");
		container.setHeight("290px");
		//container.setBorderWidth(1);
		container.getElement().getStyle().setBackgroundColor("orange");

	    resultsTable = new FlexTable();
	    resultsTable.setStylePrimaryName("divCenter");
	    resultsTable.getElement().getStyle().setMarginTop(3, Unit.PX);
	    scroll = new ScrollPanel();
	    scroll.setWidth("228px");
	    scroll.setHeight("290px");
	    scroll.add(resultsTable);
	    container.add(scroll);
	    //container.set

	    vertPanelEspera = new VerticalPanel();
	    container.add(vertPanelEspera);
		//vertPanelEspera.setStylePrimaryName("panelEspera");
		vertPanelEspera.getElement().getStyle().setPosition(Position.RELATIVE);
		//vertPanelEspera.getElement().getStyle().setTop(0, Unit.PX);
		//vertPanelEspera.getElement().getStyle().setLeft(0, Unit.PX);
		vertPanelEspera.getElement().getStyle().setBackgroundColor("red");
		vertPanelEspera.getElement().getStyle().setOpacity(0.5);
		vertPanelEspera.setWidth("100%");
		vertPanelEspera.setHeight("100%");
		vertPanelEspera.add(new Label("aguarde..."));
		
		
		listImages = new ArrayList<String>(0);
		numImagensASeremBuscadas = 0;
		numImagensCarregadas = 0;
		status = -1; // busca nao executada;

		//inicializa options
	    try {
	    	options = new SearchControlOptions();
	    } catch (Exception e) {
			//Window.alert("erro ao criar o option");
			//Window.alert("e.printstack = [" + e.getMessage() + "]");
			//Window.alert(e.getLocalizedMessage());
			//for (StackTraceElement s: e.getStackTrace()) {
			//	Window.alert(s.getFileName() + ", " + s.getLineNumber() + ", [" + s.getMethodName() + "]");
			//}
		}
	    if (options == null) {
	    	Window.alert("option nulo..tentando novamente..");
	    	try {
	    		options = new SearchControlOptions(new Search[]{});	
		    } catch (Exception e) {
		    	//Window.alert("novo erro ao criar o option");
				//Window.alert("e.printstack = [" + e.getMessage() + "]");
				//Window.alert(e.getLocalizedMessage());
				//for (StackTraceElement s: e.getStackTrace()) {
				//	Window.alert(s.getFileName() + ", " + s.getLineNumber() + ", [" + s.getMethodName() + "]");
				//}
		    }
	    }

	    if (options == null) {
	    	//Window.alert("option final ficou nulo..");
	    }
	}

	public BuscaImagemWidget(String busca) {
		this();
		setBusca(busca);
	}

	public void setBusca(final String busca) {

		status = -1;

		//Window.alert("iniciando busca buscaimagemwidget...1");
		listImages.clear();
		//Window.alert("iniciando busca buscaimagemwidget...2");

		//Window.alert("iniciando busca buscaimagemwidget...3");
	    ImageSearch webSearch = new ImageSearch();
	    //Window.alert("iniciando busca buscaimagemwidget...4");
	    webSearch.setNoHtmlGeneration();
	    //Window.alert("iniciando busca buscaimagemwidget...5");
	    webSearch.setResultSetSize(ResultSetSize.LARGE);
	    //Window.alert("iniciando busca buscaimagemwidget...6");
	    options.add(webSearch);
	    //Window.alert("iniciando busca buscaimagemwidget...7");
	    
	    //Window.alert("Seach control iniciado...");
	    SearchControl control;
	    if (options == null) {
	    	control = new SearchControl(null);
	    } else {
	    	control = new SearchControl(options);
	    }
	    //Window.alert("Seach control ok!");

	    control.addSearchResultsHandler(new SearchResultsHandler() {
	    	public void onSearchResults(final SearchResultsEvent event) {

	    		JsArray<? extends Result> results = event.getResults();
	    		int numResults = results.length();
	    		System.out.println("numero de resultados desta pagina: " + numResults);

	    		//Window.alert("numero de resultados desta pagina: " + results.length());

	    		vertPanelEspera.getElement().getStyle().setVisibility(Visibility.VISIBLE);
	    		resultsTable.clear();
	    		//container.remove(scroll);
	    		//numImagensASeremBuscadas = 0;
	    		numImagensCarregadas = 0;

	    		status = 1; // busca executada, carregando imagens...
	    		numImagensASeremBuscadas = results.length();

	    		if (numResults > 0) {
	    		
		    		System.out.println("estimatedResultCount: " + event.getSearch().getCursor().getEstimatedResultCount());
		    		System.out.println("pageIndex: " + event.getSearch().getCursor().getCurrentPageIndex());
	
		    		final int pageNumber = event.getSearch().getCursor().getCurrentPageIndex();
		    		final int numPaginas = event.getSearch().getCursor().getPages().length();
	
		    		System.out.println("numero de paginas: " + numPaginas);
		    		System.out.println("Pagina atual: " + pageNumber);
		    		
	
		    		int i = 0;
		    		for (i = 0; i < results.length(); i++) {
		    			if (results.get(i).getResultClass().equals(ResultClass.IMAGE_SEARCH_RESULT)) {
	
		    				WebResult result = (WebResult) results.get(i);
	
		    				Image img = new Image();
		    				img.setTitle(result.getUrl());
		    				img.setUrl(result.getUrl());
		    				img.setStylePrimaryName("bordaDupla");
		    				
		    				img.addErrorHandler(new ErrorHandler() {
								@Override
								public void onError(ErrorEvent event) {
									System.out.println("Erro ao carregar imagem: " + event.toString());
									Image i = (Image)event.getSource();
									resultsTable.remove(i);
									numImagensASeremBuscadas--;
									checkImageLoaded();
								}
							});
	
		    				img.addLoadHandler(new LoadHandler() {
								@Override
								public void onLoad(LoadEvent event) {
									numImagensCarregadas++;
									if (vertPanelEspera.getParent().equals(container)) {
										//container.remove(vertPanelEspera);
										vertPanelEspera.getElement().getStyle().setVisibility(Visibility.HIDDEN);
									}
									if (!scroll.getParent().equals(container)) {
										container.add(scroll);
									}
	
									Image img = (Image)event.getSource();
				    				img.addClickHandler(new ClickHandler() {
										@Override
										public void onClick(ClickEvent event) {
											Image i = (Image)event.getSource();
	
											int numImagensAnterior = listImages.size();
	
											//System.out.println("clicou na imagem src=" + i.getTitle() + ", style=[" + i.getStylePrimaryName() + "]");
											if (!i.getStylePrimaryName().equals("bordaDuplaSelecionada")) {
												listImages.add(i.getTitle());
												i.setStylePrimaryName("bordaDuplaSelecionada");
											} else {
												i.setStylePrimaryName("bordaDupla");
												listImages.remove(i.getTitle());
											}
	
											//System.out.println("numImagensAnterior = " + numImagensAnterior + ", listImages.size() = " + listImages.size());
											if (listImages.size() > 0 && numImagensAnterior == 0) {
												handlerManager.fireEvent(new ImagemDisponivelEvent(this));
									    		btnDone.setEnabled(true);
									    		btnDone.getElement().getStyle().setFontWeight(FontWeight.BOLD);
	
											} else if (numImagensAnterior > 0 && listImages.size() == 0) {
												handlerManager.fireEvent(new ImagemNaoDisponivelEvent(this));
									    		btnDone.setEnabled(false);
									    		btnDone.getElement().getStyle().setFontWeight(FontWeight.LIGHTER);
											}
										}
									});
				    				checkImageLoaded();
								}
							});
	
		    				img.setSize("100px", "100px");
		    				int row = i / 2;
		    				int col = i % 2;
		    				resultsTable.setWidget(row, col, img);
		    			}
		    		}
		    		Button btnMaisResultados = new Button(constants.mais());
		    		btnMaisResultados.setStylePrimaryName("btnMoreResults");
		    		btnMaisResultados.addClickHandler(new ClickHandler() {
						@Override
						public void onClick(ClickEvent ev) {
							event.getSearch().gotoPage(pageNumber + 1);
						}
					});
	
		    		Button btnMenosResultados = new Button(constants.menos());
		    		btnMenosResultados.setStylePrimaryName("btnMoreResults");
		    		btnMenosResultados.addClickHandler(new ClickHandler() {
						@Override
						public void onClick(ClickEvent ev) {
							event.getSearch().gotoPage(pageNumber - 1);
						}
					});
	
		    		btnDone = new Button(constants.feito());
		    		btnDone.setStylePrimaryName("btnMoreResults");
		    		if (listImages.size() > 0) {
		    			btnDone.setEnabled(true);
			    		btnDone.getElement().getStyle().setFontWeight(FontWeight.BOLD);
		    		} else {
		    			btnDone.setEnabled(false);
		    			btnDone.getElement().getStyle().setFontWeight(FontWeight.LIGHTER);
		    		}
		    		btnDone.setWidth("100%");
		    		btnDone.addClickHandler(new ClickHandler() {
						@Override
						public void onClick(ClickEvent ev) {
							handlerManager.fireEvent(new ImagensJaSelecionadasEvent(this));
							status = 2;
						}
					});
	
		    		int row = (results.length() / 2) + 1;//resultsTable.getRowCount();
		    		//Window.alert("row: " + row);
	
		    		if (pageNumber > 0) {
		    			resultsTable.setWidget(row, 0, btnMenosResultados);
		    		}
	
		    		if (pageNumber < numPaginas && numPaginas > 1) {
		    			resultsTable.setWidget(row, 1, btnMaisResultados);
		    		}
	
		    		row++;
		    		resultsTable.setWidget(row, 0, btnDone);
		    		resultsTable.getFlexCellFormatter().setColSpan(row, 0, 2);
	    		} else {
	    			
	    			resultsTable.setWidget(0, 0, new Label("Sem resultados"));

	    		}
	    	}
	    });

	    //Window.alert("vai executar a busca...");
	    control.execute(busca);
	    //Window.alert("busca executada...");
	}

	private void checkImageLoaded() {
		if (numImagensASeremBuscadas == numImagensCarregadas && numImagensASeremBuscadas != 0) {
			handlerManager.fireEvent(new BuscaImagemExecutadaEvent(this));
			status = 2;
			//Window.alert("Todas as imagens foram carregadas...");
		}
	}

	public ArrayList<String> getSelectedImagesSource() {
		return listImages;
	}

	public void setSelectedImagesSource(ArrayList<String> listImages) {
		this.listImages = listImages;
	}

	@Override
	protected void onLoad() {
		super.onLoad();
	}

	public void addImagemSelecionadaHandler(BuscaImagemEventHandler handler) {
		handlerManager.addHandler(ImagemDisponivelEvent.TYPE, handler);
		handlerManager.addHandler(ImagemNaoDisponivelEvent.TYPE, handler);
		handlerManager.addHandler(ImagensJaSelecionadasEvent.TYPE, handler);
	}

	public void addBuscaImagemExecutadaHandler(BuscaImagemExecutadaEventHandler handler) {
		handlerManager.addHandler(BuscaImagemExecutadaEvent.TYPE, handler);
	}
}